package cn.b504.qpcr.impls;

import cn.b504.qpcr.entity.save.Sheet;
import cn.b504.qpcr.interfaces.Excel;
import cn.b504.qpcr.utils.ExcelUtils;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;

@Service
public class ExcelImpl implements Excel {
  @Override
  public XSSFWorkbook generate(List<Sheet> sheets) {
    XSSFWorkbook workbook = new XSSFWorkbook();
    sheets.forEach(it -> {
      XSSFSheet sheet = workbook.createSheet(getUniqueSheetName(workbook, it.getName()));
      ExcelUtils.addHeadData2Sheet(it.getHead(), sheet);
      ExcelUtils.addBodyData2Sheet(it.getBody(), sheet);
    });
    return workbook;
  }

  private String getUniqueSheetName(XSSFWorkbook workbook, String originName) {
    originName = originName.replaceAll("['*/:?\\[\\]\\\\]", "");
    if (originName.length() == 0) {
      return UUID.randomUUID().toString();
    }
    if (originName.length() > 27) {
      originName = originName.substring(0, 27);
    }
    int repeatCount = 0;
    String name = originName;
    try {
      Method methodContainsSheet = XSSFWorkbook.class.getDeclaredMethod("containsSheet", String.class, int.class);
      methodContainsSheet.setAccessible(true);
      Field filedSheets = XSSFWorkbook.class.getDeclaredField("sheets");
      filedSheets.setAccessible(true);
      while ((boolean) methodContainsSheet.invoke(workbook, name, ((List<?>)filedSheets.get(workbook)).size())) {
        name = originName + "_" + (++repeatCount);
      }
      return name;
    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) {
      e.printStackTrace();
      return UUID.randomUUID().toString();
    }
  }
}
